//
//  BECodingExtension.swift
//  BasicExtensions
//
//  Created by JY_NEW on 2022/8/31.
//

import Foundation

extension NSCoding {
    public static func load(from directory: FileManager.SearchPathDirectory = .documentDirectory, in domainMask: FileManager.SearchPathDomainMask = .userDomainMask, path: String) -> Self? {
        if let url = FileManager.default.urls(for: directory, in: domainMask).first?.appendingPathComponent(path),
           let data = try? Data(contentsOf: url),
           let instance = try? Self.deserialize(data) {
            return instance
        }
        return nil
    }
    public static func load(from directory: FileManager.SearchPathDirectory = .documentDirectory, in domainMask: FileManager.SearchPathDomainMask = .userDomainMask, pathOfDirectory: String) -> [Self] {
        if let url = FileManager.default.urls(for: directory, in: domainMask).first?.appendingPathComponent(pathOfDirectory),
           let files = try? FileManager.default.contentsOfDirectory(atPath: url.path) {
                return files.compactMap {
                    let path = url.appendingPathComponent($0)
                    if let data = try? Data(contentsOf: path),
                       let instance = try? Self.deserialize(data) {
                        return instance
                    }else {
                        return nil
                    }
                }
        }
        return []
    }
    public func save(to directory: FileManager.SearchPathDirectory = .documentDirectory, in domainMask: FileManager.SearchPathDomainMask = .userDomainMask, path: String) {
        if let url = FileManager.default.urls(for: directory, in: domainMask).first?.appendingPathComponent(path) {
            let directory = url.deletingLastPathComponent()
            /// 创建上下文目录
            if !FileManager.default.fileExists(atPath: directory.path) {
                try? FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
            }
            try? self.serialize().write(to: url)
        }
    }
    /// 删除文件
    public static func remove(from directory: FileManager.SearchPathDirectory = .documentDirectory, in domainMask: FileManager.SearchPathDomainMask = .userDomainMask, path: String) {
        if let url = FileManager.default.urls(for: directory, in: domainMask).first?.appendingPathComponent(path) {
            /// 删除文件
            if FileManager.default.fileExists(atPath: url.path) {
                try? FileManager.default.removeItem(at: url)
            }
        }
    }
}
extension Int: BEDecodable {
    public static func decode(for coder: NSCoder, key: String) -> Int {
        return coder.decodeInteger(forKey: key)
    }
}
extension Int32: BEDecodable {
    public static func decode(for coder: NSCoder, key: String) -> Int32 {
        return coder.decodeInt32(forKey: key)
    }
}
extension Int64: BEDecodable {
    public static func decode(for coder: NSCoder, key: String) -> Int64 {
        return coder.decodeInt64(forKey: key)
    }
}
extension Float: BEDecodable {
    public static func decode(for coder: NSCoder, key: String) -> Float {
        return coder.decodeFloat(forKey: key)
    }
}
extension Double: BEDecodable {
    public static func decode(for coder: NSCoder, key: String) -> Double {
        return coder.decodeDouble(forKey: key)
    }
}
extension CGPoint: BEDecodable {
    public static func decode(for coder: NSCoder, key: String) -> CGPoint {
        return coder.decodeCGPoint(forKey: key)
    }
}
extension CGSize: BEDecodable {
    public static func decode(for coder: NSCoder, key: String) -> CGSize {
        return coder.decodeCGSize(forKey: key)
    }
}
extension CGRect: BEDecodable {
    public static func decode(for coder: NSCoder, key: String) -> CGRect {
        return coder.decodeCGRect(forKey: key)
    }
}
extension CGAffineTransform: BEDecodable {
    public static func decode(for coder: NSCoder, key: String) -> CGAffineTransform {
        return coder.decodeCGAffineTransform(forKey: key)
    }
}
extension UIEdgeInsets: BEDecodable {
    public static func decode(for coder: NSCoder, key: String) -> UIEdgeInsets {
        return coder.decodeUIEdgeInsets(forKey: key)
    }
}
@available(iOS 11.0, *)
extension NSDirectionalEdgeInsets: BEDecodable {
    public static func decode(for coder: NSCoder, key: String) -> NSDirectionalEdgeInsets {
        return coder.decodeDirectionalEdgeInsets(forKey: key)
    }
}
extension UIOffset: BEDecodable {
    public static func decode(for coder: NSCoder, key: String) -> UIOffset {
        return coder.decodeUIOffset(forKey: key)
    }
}
extension Bool: BEDecodable {
    public static func decode(for coder: NSCoder, key: String) -> Bool {
        return coder.decodeBool(forKey: key)
    }
}
extension String: BEMaybeDecodable {
    public static func decode(for coder: NSCoder, key: String) -> String? {
        return coder.decodeObject(forKey: key) as? String
    }
}
extension Date: BEMaybeDecodable {
    public static func decode(for coder: NSCoder, key: String) -> Date? {
        return coder.decodeObject(forKey: key) as? Date
    }
}
extension Array: BEMaybeDecodable {
    public static func decode(for coder: NSCoder, key: String) -> Self? {
        return coder.decodeObject(forKey: key) as? Self
    }
}
extension Dictionary: BEMaybeDecodable {
    public static func decode(for coder: NSCoder, key: String) -> Self? {
        return coder.decodeObject(forKey: key) as? Self
    }
}
extension NSCoder {
    public func decode<T: BEDecodable>(forKey key: String) -> T {
        return T.decode(for: self, key: key)
    }
    public func decode<T: BEDecodable>(forKey key: String) -> T? {
        return self.decodeObject(forKey: key) as? T
    }
    public func decode<T: BEMaybeDecodable>(forKey key: String) -> T? {
        return T.decode(for: self, key: key)
    }
}
